package com.shelpe.services.algorithm.autoDrive;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shelpe.services.algorithm.entity.jpa.AutoMaintainLog;
import com.shelpe.services.algorithm.repository.jpa.AutoMaintainLogRepository;
import com.shelpe.services.algorithm.sustain.SustainRule;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class AutoDriveKeywordSustainRule implements SustainRule<AutoDriveKeywordSustainer> {

	@Autowired
	private AutoMaintainLogRepository autoMaintainLogRepository;
	
	@Override
	public boolean check(AutoDriveKeywordSustainer entity) {
		if(log.isDebugEnabled()){
			log.debug("keyword: {}", entity.getKeyword());
			log.debug("last 3 days' state: {}", entity.getLast3daysReport());
			log.debug("last 7 days' state: {}", entity.getLast7daysReport());
			log.debug("last 3 days' insight: {}", entity.getLast3InsightData());
		}
		return entity.getLast3daysReport() != null;
	}

	@Override
	public boolean prepare(AutoDriveKeywordSustainer entity) {
		return true;
	}

	@Override
	public SustainRule.SustainStatus sustain(AutoDriveKeywordSustainer entity) {
		float threhold = 0.5f;
		int avgPV = entity.getLast3daysReport().getImpressions();
		float avgCtr = entity.getLast3daysReport().getCtr();
		if(entity.getLast3InsightData() != null){
			if(entity.getLast3InsightData().getCompetition() != 0){
				avgPV = 5 * entity.getLast3InsightData().getImpression() / entity.getLast3InsightData().getCompetition();
			}
			avgCtr = NumberUtils.toFloat(entity.getLast3InsightData().getCtr());
			if(entity.getLast3InsightData().getCpc() != null && NumberUtils.isNumber(entity.getLast3InsightData().getCpc())){
				threhold = NumberUtils.toFloat(entity.getLast3InsightData().getCpc()) * 0.3f;
			}
		}
		
		int pqr = 0;
		float last3DaysClick = entity.getLast3daysReport().getImpressions() * entity.getLast3daysReport().getCtr();
		if(last3DaysClick > 0){
			pqr = ((entity.getLast3daysReport().getCost()/last3DaysClick) <= threhold)?1:-1;
		}else{
			pqr = (entity.getLast3daysReport().getImpressions() == 0 && entity.getKeyword().getMaxPrice() <= threhold)?1:0;
		}
		
		
		int lowAvgposThres = 40;
		int highAvgposThres = 16;
		int lowQscoreThres = 3;
		int middleQscoreThres = 6;
		int highQscoreThres = 8;
		int maxAdjustPrice = 50;
		float adjustPriceRatio = 0.1f;
		
		int adjustPrice = 0;
		if(entity.getLast3InsightData() != null && NumberUtils.isNumber(entity.getLast3InsightData().getCpc())){
			adjustPrice = (int) (NumberUtils.toFloat(entity.getLast3InsightData().getCpc()) * 100 * adjustPriceRatio);
		}
		if(adjustPrice == 0){
			adjustPrice = (int) (entity.getKeyword().getMaxPrice() * adjustPriceRatio);
		}
		adjustPrice = Math.min(adjustPrice, maxAdjustPrice);
		entity.setAdjustPrice(adjustPrice);
		
		SustainRule.SustainStatus ss = SustainRule.SustainStatus.keep;
		int action = 0;
		
		/**
		 * 检查质量得分
		 * - 质量得分低的 
		 * - 长期没有pv且质量得分不高
		 */
		int days = DateUtils.truncatedCompareTo(new Date(), entity.getKeyword().getCreateTime(), Calendar.DATE);
		if(entity.getKeyword().getQscore() > 0 && (entity.getKeyword().getQscore() <= lowQscoreThres || 
				(entity.getLast7daysReport() != null && entity.getLast7daysReport().getImpressions() == 0 && entity.getKeyword().getQscore() < highQscoreThres && days < 7))){
			ss = SustainRule.SustainStatus.remove;
			action = 3;
		}
		
		/**，
		 * 检查转化率
		 *  - 如果连续3天都有较多点击（平均点击>=10），但是没有转化，则删除。如果连续3天得平均点击>=4，而没有转化，则降价。
		 *  - 保留观察, 如果已经一周了还是无转化, 删除
		 */
		if(ss == SustainRule.SustainStatus.keep){
			Date ago7 = DateUtils.addDays(DateUtils.truncate(new Date(), Calendar.DATE), -7);
			List<AutoMaintainLog> logs = this.autoMaintainLogRepository.findByKeywordIDAndDateAfter(entity.getKeyword().getKeywordId(), ago7);
			if(logs.size() > 3){
				int avg = -1;
				int lessChanges = 0;
				for(AutoMaintainLog log: logs){
					if(avg >= 0){
						avg = (avg + log.getClick()) / 2;
					}else{
						avg = log.getClick();
					}
					if(log.getPv() == 2 && log.getCtr() < 2 && log.getQscore() > 1 && log.getAction() == "1"){
						lessChanges = lessChanges + 1;
					}
				}
				if(entity.getLast3daysReport().getSale() == 0){
					if(avg >= 10){
						ss = SustainRule.SustainStatus.remove;
						action = 3;
					}else if(avg >= 4){
						entity.getKeyword().setMaxPrice(entity.getKeyword().getMaxPrice() - adjustPrice);
						ss = SustainRule.SustainStatus.pricing;
						action = 2;
					}
				}else if(pqr == 1 && entity.getKeyword().getQscore() > middleQscoreThres 
						&& entity.getLast3daysReport().getImpressions() > avgPV
						&& entity.getLast3daysReport().getCtr() <= avgCtr){
					if(logs.size() > 2 && lessChanges >= 2){
						ss = SustainRule.SustainStatus.remove;
						action = 3;
					}
				}
				
			}
		}
		
		if(ss == SustainRule.SustainStatus.keep){
			//高展现量 ＋ 高点击率
			if(entity.getLast3daysReport().getImpressions() > avgPV && entity.getLast3daysReport().getCtr() > avgCtr){
				//高性价比 ＋ 排名中后 ＋ 有转化
				if(pqr == 1 && entity.getLast3daysReport().getAvgpos() > highAvgposThres && entity.getLast3daysReport().getSale() > 0){
					entity.getKeyword().setMaxPrice(entity.getKeyword().getMaxPrice() + adjustPrice);
					ss = SustainRule.SustainStatus.pricing;
					action = 1;
				}
				//低性价比 ＋ 排名中前
				if(pqr == -1 && entity.getLast3daysReport().getAvgpos() < lowAvgposThres){
					entity.getKeyword().setMaxPrice(entity.getKeyword().getMaxPrice() - adjustPrice);
					ss = SustainRule.SustainStatus.pricing;
					action = 2;
				}
			}
			//高展现量 ＋ 低点击率
			if(entity.getLast3daysReport().getImpressions() > avgPV && entity.getLast3daysReport().getCtr() <= avgCtr){
				//高性价比 ＋ 中前质量得分
				if(pqr == 1 && entity.getKeyword().getQscore() > middleQscoreThres){
					//TODO: 保留观察, 如果已经一周了还是无转化, 删除
					entity.getKeyword().setMaxPrice(entity.getKeyword().getMaxPrice() + adjustPrice);
					ss = SustainRule.SustainStatus.pricing;
					action = 1;
				}
				//低性价比 ＋ 排名已靠前
				if(pqr == -1 && entity.getLast3daysReport().getAvgpos() < lowAvgposThres){
					entity.getKeyword().setMaxPrice(entity.getKeyword().getMaxPrice() - adjustPrice);
					ss = SustainRule.SustainStatus.pricing;
					action = 2;
				}
			}
			
			//低展现量 ＋ 高质量得分／中质量得分但点击率高/有转化
			if(entity.getLast3daysReport().getImpressions() <= avgPV && entity.getLast3daysReport().getImpressions() > 0 && pqr != 0){
				if(entity.getKeyword().getQscore() > middleQscoreThres || 
						(entity.getKeyword().getQscore() <= middleQscoreThres && entity.getLast3daysReport().getCtr() >= avgCtr) ||
						entity.getLast3daysReport().getCtr() > avgCtr){
					entity.getKeyword().setMaxPrice(entity.getKeyword().getMaxPrice() + (pqr * adjustPrice));
					ss = SustainRule.SustainStatus.pricing;
					action = 1;
				}
			}
			
			//无展现量 ＋ 高质量分 ＋ 高性价比
			if(entity.getLast3daysReport().getImpressions() == 0 && entity.getKeyword().getQscore() >= highQscoreThres){
				if(pqr == 1){
					entity.getKeyword().setMaxPrice(entity.getKeyword().getMaxPrice() + adjustPrice);
					ss = SustainRule.SustainStatus.pricing;
					action = 1;
				}
			}
		}
		
		if(ss == SustainRule.SustainStatus.pricing && entity.getAdgroup() != null && entity.getAdgroup().getLimit() > 0){
			if(entity.getKeyword().getMaxPrice() > entity.getAdgroup().getLimit()){
				entity.getKeyword().setMaxPrice(entity.getAdgroup().getLimit());
			}
		}
		
		AutoMaintainLog log = new AutoMaintainLog();
		log.setKeywordID(entity.getKeyword().getKeywordId());
		log.setDate(new Date());
		log.setCvr(entity.getLast3daysReport().getSale() == 0?0:1);
		log.setPv(entity.getLast3daysReport().getImpressions() > 0?(entity.getLast3daysReport().getImpressions()>avgPV?2:1):0);
		log.setCtr(entity.getLast3daysReport().getCtr()>0?(entity.getLast3daysReport().getCtr()>avgCtr?2:1):0);
		int level = 0;
		if(entity.getKeyword().getQscore() > highQscoreThres){
			level = 3;
		}else if(entity.getKeyword().getQscore() > middleQscoreThres){
			level = 2;
		}else if(entity.getKeyword().getQscore() > lowQscoreThres){
			level = 1;
		}
		log.setQscore(level);
		level = 0;
		if(entity.getLast3daysReport().getAvgpos() < highAvgposThres){
			level = 1;
		}else if(entity.getLast3daysReport().getAvgpos() < lowAvgposThres){
			level = 2;
		}
		log.setAvgpos(level);
		log.setAction(action + "");
		this.autoMaintainLogRepository.save(log);
		
		return ss;
	}

	@Override
	public boolean maintain(AutoDriveKeywordSustainer entity,
			SustainRule.SustainStatus status) {
		return true;
	}

	@Override
	public boolean mark(AutoDriveKeywordSustainer entity) {
		return true;
	}

}
